// import { getSongUrl, getSongDetail } from '@/api'
import { isObject } from '@/utils'
import { Toast } from 'vant'
import { getSongDetail, getSongUrl } from '@/api/module/song'

const PLAY_MODE = {
  LOOP: 0,
  SINGLE: 1,
  RANDOM: 2
}

const state = {
  // 播放器控制
  audio: null, // audio 元素
  isPlay: false, // 是否正在播放
  showPlayer: false, // 是否显示播放界面
  /** 定义播放列表：
   * 1.当用户在歌单/专辑/排行榜中点击播放时，将切换播放列表
   * 2.当用户在以上区域之外(如轮播、首页单曲推荐)点击播放、或在歌单/专辑/排行榜中选择 “添加到播放列表”，将添加而不是切换当前播放列表
   * 3.当播放另一首歌位于当前播放列表时，将核对 playlistId，若相同则不作操作；不同时将替换播放列表
   */
  playlist: [], // 播放列表，包含歌曲详情
  playlistId: 0, // 播放列表 id，默认为 0，切换播放列表时替换为对应的 id
  playMode: PLAY_MODE.LOOP, // 播放模式，默认循环播放

  // 当前歌曲信息
  songId: 0, // 歌曲 id
  songName: '', // 歌曲名
  songAr: [], // 歌手列表
  songPicUrl: '', // 歌曲封面
  songDt: 0, // 歌曲总时长
  songUrl: '' // 歌曲 url
}

/** 关乎命名前缀
 * toggle：在两个之间切换
 * change：修改属性
 * update：更新属性
 */
const mutations = {
  'TOGGLE_SHOW_PLAYER' (state) {
    state.showPlayer = !state.showPlayer
  },
  'CHANGE_SONG' (state, song) {
    // console.log('In mutation, song is:', song)
    state.songId = song.id || 0
    state.songName = song.name || ''
    state.songAr = [].concat(song.ar) || []
    state.songPicUrl = song.al.picUrl || ''
    state.songDt = song.dt || 0
    state.songUrl = song.url || ''
  },
  'TOGGLE_PLAY' (state) {
    state.isPlay = !state.isPlay
  },
  'GET_AUDIO' (state, audio) {
    state.audio = audio
  },
  'INIT_PLAYER' (state) {
    state.audio.play()
    state.audio.pause()
  },
  'TOGGLE_SHOW_PLAYLIST' (state) {
    state.showPlaylist = !state.showPlaylist
  },
  'ADD_TO_PLAYLIST' (state, song) {
    state.playlist.push(song)
    // console.log(state.playlist)
  },
  'UPDATE_PLAYLIST' (state, tracks) {
    state.playlist = [].concat(tracks)
    // console.log(state.playlist)
  },
  'REMOVE_FROM_PLAYLIST' (state, songId) {
    state.playlist = state.playlist.filter(v => v.id !== songId)
  },
  'CLEAR_PLAYLIST' (state) {
    state.playlist = []
    state.playlistId = 0
  },
  'UPDATE_PLAYLIST_ID' (state, playlistId) {
    state.playlistId = playlistId
  },
  'TOGGLE_PLAY_MODE' (state) {
    if (state.playMode === PLAY_MODE.LOOP) {
      state.playMode = PLAY_MODE.SINGLE
    } else if (state.playMode === PLAY_MODE.SINGLE) {
      state.playMode = PLAY_MODE.RANDOM
    } else {
      state.playMode = PLAY_MODE.LOOP
    }
  }
}

const handleGetSongUrl = async songId => {
  const res = await getSongUrl(songId)
  const { data } = res.data
  const url = data[0].url
  return url
}

const handleGetRandomSong = (playlist, currentId) => {
  if (playlist.length === 1) return playlist[0]
  const length = playlist.length
  const currentIndex = playlist.findIndex(v => v.id === currentId)
  let randomIndex = currentIndex
  // 简单判断逻辑：只要下一首不是当前播放的即可
  while (randomIndex === currentIndex) {
    randomIndex = Math.floor(Math.random() * length)
  }

  return playlist[randomIndex]
}

const isSongExist = (playlist, songId) => {
  return playlist.map(v => v.id).includes(songId)
}

const actions = {
  toggleShowPlayer ({ commit }) {
    commit('TOGGLE_SHOW_PLAYER')
  },
  /**
   * number: song id
   *  + 从歌单/专辑/排行榜外的地方发起，如首页轮播、推荐音乐等
   *  + tips 1: 第一次点击时会播放，再次点击时会跳转到 player 界面
   *  + tips 2: 这个歌曲会被添加至现有播放列表
   * object: song detail
   *  + 从歌单/专辑/排行榜发起，已包含歌曲信息，只需请求 song url
   *  + tips 1: 点击同一歌曲时只会跳转到 player 界面
   *  + tips 2: 这时会替换播放列表为相应的 歌单/专辑/排行榜
   * @param {Number | Object} song
   * @param {Boolean} toPlayer
   */
  async changeSong ({ commit, state },
    {
      song, // songId || song
      toPlayer = true, // 是否切换到播放器
      addPlaylist = true // 是否需要添加到播放列表
    } = {}) {
    let realSong = song

    // 传入 songId 时，先获取歌曲详情
    if (typeof song === 'number') {
      const res = await getSongDetail(song)
      realSong = res.data.songs[0]
    }

    if (isObject(realSong)) {
      // 歌曲正在播放，切换到播放界面
      if (realSong.id === state.songId && !state.showPlayer) {
        return commit('TOGGLE_SHOW_PLAYER')
      }
      const url = await handleGetSongUrl(realSong.id)
      // console.log('Url: %s', url)
      realSong.url = url
      if (!url) {
        return Toast.fail({
          message: '暂无资源!',
          closeOnClick: true,
          className: 'toast--fail'
        })
      }
      // 添加到播放列表
      addPlaylist &&
      !isSongExist(state.playlist, realSong.id) &&
      commit('ADD_TO_PLAYLIST', realSong)
      // 提交歌曲信息
      commit('CHANGE_SONG', realSong)
      // 保证歌曲会播放
      !state.isPlay && commit('TOGGLE_PLAY')
    }

    // 最后，切换到播放界面
    toPlayer && commit('TOGGLE_SHOW_PLAYER')
  },
  togglePlayMode ({ commit }) {
    commit('TOGGLE_PLAY_MODE')
  },
  togglePlay ({ commit, state }) {
    // 没有 songId(即播放列表为空)时不能播放
    // Todo：有些歌曲没有版权，需要兼容
    if (!state.songId) {
      Toast.fail({
        message: '播放列表为空!\n快去添加喜欢的歌曲吧~',
        closeOnClick: true,
        className: 'toast--fail'
      })
      return
    }
    if (state.isPlay) {
      state.audio.pause()
    } else {
      state.audio.play()
    }
    commit('TOGGLE_PLAY')
  },
  togglePlayPrev ({ dispatch, state }) {
    if (state.playMode === PLAY_MODE.RANDOM) {
      const nextSong = handleGetRandomSong(state.playlist, state.songId)
      dispatch('changeSong', { song: nextSong, toPlayer: false })
    } else {
      const index = state.playlist.findIndex(v => v.id === state.songId)
      // 处理边界：当前播放为播放列表第一首时，切换到最后一首
      const prevSong = index === 0
        ? state.playlist[state.playlist.length - 1]
        : state.playlist[index - 1]
      dispatch('changeSong', { song: prevSong, toPlayer: false })
    }
  },
  togglePlayNext ({ dispatch, state }) {
    if (state.playMode === PLAY_MODE.RANDOM) {
      const nextSong = handleGetRandomSong(state.playlist, state.songId)
      dispatch('changeSong', { song: nextSong, toPlayer: false })
    } else {
      const index = state.playlist.findIndex(v => v.id === state.songId)
      // 处理边界：当前播放为最后一首时，切换到第一首
      const nextSong = index === state.playlist.length - 1
        ? state.playlist[0]
        : state.playlist[index + 1]
      dispatch('changeSong', { song: nextSong, toPlayer: false })
    }
  },
  initPlayer ({ commit }) {
    commit('INIT_PLAYER')
  },
  getAudio ({ commit }, audio) {
    commit('GET_AUDIO', audio)
  },
  addToPlaylist ({ commit }, song) {
    commit('ADD_TO_PLAYLIST', song)
  },
  removeFromPlaylist ({ commit, state, dispatch }, id) {
    // 删除的是正在播放的歌曲
    if (state.songId === id) {
      dispatch('togglePlayNext')
    }

    commit('REMOVE_FROM_PLAYLIST', id)
  },
  updatePlaylist ({ commit, state }, { tracks, playlistId }) {
    // 在当前播放列表中切换，不再作操作
    if (state.playlistId === playlistId) return
    commit('UPDATE_PLAYLIST', tracks)
    commit('UPDATE_PLAYLIST_ID', playlistId)
  },
  clearPlaylist ({ commit, state }) {
    commit('toggle_show_player') // 隐藏播放器
    commit('change_song', {}) // 清空歌曲信息
    if (state.isPlay) {
      commit('toggle_play') // 暂停播放
    }
    commit('CLEAR_PLAYLIST') // 清空播放列表和 playlistId
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}
